package ar.edu.itba.pod.Legajo47342.communication.handlers;

import java.rmi.RemoteException;

import ar.edu.itba.pod.Legajo47342.Node;
import ar.edu.itba.pod.Legajo47342.communication.payload.ResourceTransferMessagePayloadImpl;
import ar.edu.itba.pod.Legajo47342.market.MarketImpl;
import ar.edu.itba.pod.simul.communication.Message;
import ar.edu.itba.pod.simul.communication.MessageType;
import ar.edu.itba.pod.simul.communication.Transactionable;
import ar.edu.itba.pod.simul.communication.payload.Payload;
import ar.edu.itba.pod.simul.communication.payload.ResourceRequestPayload;
import ar.edu.itba.pod.simul.market.Resource;
import ar.edu.itba.pod.simul.market.ResourceStock;

import com.google.common.collect.Multiset;

public class ResourceRequestHandler implements Handler {
	
	private Node node;

	public ResourceRequestHandler(Node node) {
		super();
		this.node = node;
	}


	@Override
	public void handle(Message message) {
		ResourceRequestPayload inPay = (ResourceRequestPayload) message.getPayload();
		Resource reqRes = inPay.getResource();
		int reqAmount = inPay.getAmountRequested();
		Multiset<ResourceStock> selling = ((MarketImpl)node.getMarketManager().market()).getSelling();
		int toExchange = 0;
		
		synchronized (selling) {
			toExchange = sells(selling, reqRes, reqAmount);
		}
		//System.out.println("voy a cambiar: "+toExchange);
		if (toExchange <= 0) {
			return;
		}
		
		Transactionable transLocal;
		Transactionable transRemote;
		try {
			transLocal = node.getManager().getNodeCommunication();
			transRemote = node.getManager().getConnectionManager(message.getNodeId()).getNodeCommunication();
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		
		try {
			transLocal.beginTransaction(message.getNodeId(), Node.WHOLE_TRANS_WAIT);
			//transRemote.beginTransaction(message.getNodeId(), Node.TRANS_WAIT);
			
			transLocal.exchange(reqRes, toExchange, node.getNodeId(), message.getNodeId());
			transRemote.exchange(reqRes, toExchange, node.getNodeId(), message.getNodeId());
			
			transLocal.endTransaction();
			//transRemote.endTransaction();
			
		} catch (RemoteException e) {
			e.printStackTrace();
			try {
				transLocal.rollback();
				transRemote.rollback();
			} catch (RemoteException e1) {
				e1.printStackTrace();
			}
			
			return;
		}
		
		try {//seteo todo en 0 al terminar
			transLocal.rollback();
			transRemote.rollback();
		} catch (RemoteException e) {
			e.printStackTrace();
		}
			
		
	}
	
	public int sells(Multiset<ResourceStock> selling, Resource reqRes, int reqAmount) {
		for (ResourceStock r : selling) {
			if (r.resource().equals(reqRes)) {
				return Math.min(reqAmount, selling.count(r));
			}
		}
		return 0;
	}

}
